﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TakeoutExpress.Support.Linq;
using System.Workflow.Runtime;

namespace TakeoutExpress.Support.Controllers
{
    /// <summary>
    /// <author>Chris Taylor</author>
    /// <created>01.14.2008</created>
    /// <remarks>This is a support class to the WorfklowServices Implementation.  The workflow itself is to be 
    /// data agnostic.  But the implementation allows it to respond to events in order to audit or modify it. 
    /// 
    /// I guess theoretically a test would be to mock everything...  Hmmm.. </remarks>
    /// </summary>
    public class TakeoutController
    {
        private static Linq.TakeoutExpress2008DataContext dataContext;
      
        public TakeoutController(string dataContextConnectionString)
         {
             dataContext = new TakeoutExpress2008DataContext(dataContextConnectionString);
          
         }
         public TakeoutController()
         {
             // pretty much assumes we don't need a workflow runtime or datacontext as theya re static and created...
             // this is bad.. I know it.. but trying to just get Workflow in a functional pattern that makes sense.
             if (dataContext == null)//only if its not assigned
                 dataContext = new TakeoutExpress2008DataContext();
         }
         internal TakeoutUser AddTakeoutUser(int takeoutProviderId, string instructions, string userName, IEnumerable<OrderItem> orderItems)
         {
             TakeoutUser returnUser = new TakeoutUser();

             return returnUser;
         }


         public Linq.TakeoutUser CreateTakeoutUser(TakeoutProvider takeoutProvider, IEnumerable<OrderItem> orderItems, string instructions, string userName)
         {
             TakeoutUser takeoutUser = new TakeoutUser();

             List<OrderItem> orderItemClone = new List<OrderItem>(orderItems);
             takeoutUser.Instructions = instructions;
             takeoutUser.IsPaid = false;
             takeoutUser.OrderTime = DateTime.Now;
             takeoutUser.FundsSecuredTime = DateTime.Now;
             takeoutUser.Username = userName;
             takeoutUser.OrderItems.AddRange(orderItemClone);
             takeoutUser.OrderTotal = 0;
             takeoutUser.IsWorkflowApproved = false;
             //(from ti in takeoutUser.OrderItems
             // select ti.MenuItem.Price * ti.Quantity).Sum();

             takeoutProvider.TakeoutUsers.Add(takeoutUser);

             dataContext.SubmitChanges();

             // talk to the workflow.  

             DeliveryBoy.Workflow.Interfaces.ITakeoutProviderWorkflow providerWorkflowServer =
                _workflowRuntime.GetService<DeliveryBoy.Workflow.Interfaces.ITakeoutProviderWorkflow>();

             providerWorkflowServer.WFCreateTakeoutUser(takeoutProvider.Id,
                 new DeliveryBoy.Workflow.Interfaces.TakeoutProviderWorkflowAddSubscriberEventArgs(  takeoutProvider.WorkflowInstanceId.Value,
                     instructions, orderItemClone, userName));

             //providerWorkflowServer.CreateTakeoutUser(  takeoutProvider.WorkflowInstanceId.Value, -1, (IEnumerable<OrderItem>) orderItemClone, userName);
               
             //   providerWorkflowServer.CreateTakeoutUser(
             //set a wait handle here?  because the workflow will actually create the user.  

             return takeoutUser;
             
         }

        public Linq.TakeoutProvider CreateTakeoutProvider(Site site, IEnumerable<Audience> audiences, Menus menu, string userName, 
            DateTime broadcastStartTime, DateTime broadCastEndTime, int maxOrders, decimal deliveryCharge, string instructions)
        {
            TakeoutProvider returnProvider = new TakeoutProvider();

            returnProvider.Username = userName;
            returnProvider.Site = site;
             //=(System.Data.Linq.EntitySet<TakeoutProviderAudience>) audiences;
            returnProvider.StartTime = broadcastStartTime;
            returnProvider.ExpirationTime = broadCastEndTime;
            returnProvider.TakeoutCharge = deliveryCharge;
            returnProvider.MaximumOrders = maxOrders;
            returnProvider.Menus = menu;
            returnProvider.Instructions = instructions;

            // add the audiences

            // Audience[] audiencesCopy = new Audience()[0];
            // new List<Audience>(audiences).CopyTo(audiencesCopy);

            dataContext.TakeoutProviders.InsertOnSubmit(returnProvider);
            dataContext.SubmitChanges();

            List<Audience> audienceCopy = new List<Audience>(audiences);

            foreach (Audience audience in audienceCopy)
                returnProvider.TakeoutProviderAudiences.Add(
                    new TakeoutProviderAudience() { Audience = audience });


            dataContext.SubmitChanges();

            // fire up the workflow
            
            Dictionary<string, object> namedParameters = new Dictionary<string,object>();
            
            namedParameters.Add("TakeoutProviderID", returnProvider.Id);
            namedParameters.Add("BroadcastStartTime", returnProvider.StartTime);
            namedParameters.Add("BroadcastEndTime", returnProvider.ExpirationTime);
            namedParameters.Add("MaxOrders", returnProvider.MaximumOrders);

            Guid workflowInstanceId = Guid.NewGuid();
            _workflowRuntime.ServicesExceptionNotHandled += new EventHandler<ServicesExceptionNotHandledEventArgs>(_workflowRuntime_ServicesExceptionNotHandled);
            _workflowRuntime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(_workflowRuntime_WorkflowCreated);
            _workflowRuntime.WorkflowStarted += new EventHandler<WorkflowEventArgs>(_workflowRuntime_WorkflowStarted);
            _workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(_workflowRuntime_WorkflowTerminated);
             WorkflowInstance workflowInstance =_workflowRuntime.CreateWorkflow
                (typeof(DeliveryBoy.Workflow.TakeoutProviderWorkflow), namedParameters);

            
             workflowInstanceId = workflowInstance.InstanceId;
             returnProvider.WorkflowInstanceId = workflowInstanceId;
             dataContext.SubmitChanges();
             _workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(_workflowRuntime_WorkflowCompleted);
            workflowInstance.Load();
             workflowInstance.Start();
        //     mutex.WaitOne();
            

            return returnProvider;
            
        }

      

    }
}
